package
        com.qf.service.Impl;

import com.qf.exceptions.MybaseException;
import com.qf.feign.CacheService;
import com.qf.service.ISmsCheckService;
import com.qf.service.PushSubmitToQueueService;
import com.qf.utils.PhoneFormatCheckUtil;
import com.qianfeng.smsplatform.common.constants.CacheConstants;
import com.qianfeng.smsplatform.common.constants.ResutlDataEnum;
import com.qianfeng.smsplatform.common.model.Standard_Submit;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;

import java.lang.reflect.Array;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/*
 * @Data: 2021/7/13 21:28
 * */
@Service
public class SmsCheckService implements ISmsCheckService {

    private PushSubmitToQueueService pushSubmitToQueueService;
    @Autowired
    public void setPushSubmitToQueueService(PushSubmitToQueueService pushSubmitToQueueService) {
        this.pushSubmitToQueueService = pushSubmitToQueueService;
    }

    private CacheService cacheService;
    @Autowired
    public void setCacheService(CacheService cacheService) {
        this.cacheService = cacheService;
    }
    @Override
    public List<String> checkSms(String clientId, String pwd, String srcId, String ip, String content, String mobile) {
        //todo 账号和密码是去什么地方查询? 数据库? redis?
        //存的时候是 hash格式,以CLIENT:id的方式作为key保存起来了
        System.out.println("clientId-->"+clientId);

        Map clientInfoMap = cacheService.hmget(CacheConstants.CACHE_PREFIX_CLIENT + clientId);
        System.out.println("clientInfoMap-->"+clientInfoMap);
        if(clientInfoMap!=null&&clientInfoMap.size()>0){
            //        1 账号密码效验
//                根据用户名查询一波数据 然后和获取到的密码进行效验比较 如果一致则继续不一致则拦截
//          将传递的密码转换为MD5 值 然后和缓存中的密码进行比较
          String s = DigestUtils.md5DigestAsHex(pwd.getBytes(StandardCharsets.UTF_8));
//         缓存中真正获取到用户的密码MD5 值
          String userRedisPwd = (String)clientInfoMap.get("pwd");
            if(!s.equals(userRedisPwd)){
//              密码不匹配 扔个异常返回
                throw new MybaseException(ResutlDataEnum.PWDERROR );
            }

            //        2 ip 效验
//             根据当前用户 获取到他允许 的IP  然后获取到当前的访问Ip 进行判断
            String ipaddress = (String)clientInfoMap.get("ipaddress");
            System.out.println("ipaddress"+ipaddress);
            if (!ipaddress.contains(ip)) {
                throw new MybaseException(ResutlDataEnum.IPERROR);
            }
            //        3  手机号格式效验
//                    正则表达式  一次性会传递很多歌手机号 需要切割后逐个判断
            String[] mobiles = mobile.split(",");
//        手机符合规则的手机号
            List<String> ok = Arrays.stream(mobiles).filter(phoneNum ->
                    PhoneFormatCheckUtil.isPhoneLegal(phoneNum)
            ).collect(Collectors.toList());
            List<String> fail = Arrays.stream(mobiles).filter(phoneNum -> !PhoneFormatCheckUtil.isPhoneLegal(phoneNum)).collect(Collectors.toList());

//        4 短信长度效验
//                  需要获取内容
//        5 必须确定用户传递了唯一的 消息的ID
//       获取用户的唯一ID主要目的是让我们知道这个短信的ID 是什么 后面可以将这个ID 传给客户 这样客户就知道哪个短信的结果了

           Long srcIdLong;
            if(StringUtils.isEmpty(srcId)){
                //没有传递唯一的id
                throw new MybaseException(ResutlDataEnum.SRCIDERROR);
            }
            try {
                srcIdLong= Long.parseLong(srcId);
            } catch (NumberFormatException e) {
                throw new MybaseException(ResutlDataEnum.SRCIDERROR );
            }
            //TODO 发送短信,我们需要让客户等着结果吗?
            //TODO 经过分析我们发现客户没有必要等着我们这边给结果,因为数据比较多,后面我们可以有结果的时候通知客户即可,因为什么时候短信能发送完成不确定
            //TODO 所以既然客户不需要等我们的结果,我们就可以将发送短信做成异步操作,比如使用线程?MQ
//          经过剪短分析  我们得出 最好是通过mq 将短信发送出去  然后后面接受消息来处理

//          将当前的手机号信息进行封装
            List<Standard_Submit> list = ok.stream().map(mobilenum -> {
                Standard_Submit submit = new Standard_Submit();
                submit.setDestMobile(mobilenum);//设置目标手机号
                submit.setClientID(Integer.parseInt(clientId));//设置来自于哪个客户
                submit.setMessageContent(content);//设置短信内容
                submit.setSrcSequenceId(srcIdLong);//设置吓醒编号
                submit.setSendTime(new Date());//设置发送时间
                //设置发送短信的方式,比如是http接口的还是web页面的,因为只有http接口的才需要返回给用户状态报告
                submit.setSource((Integer) clientInfoMap.get("usertype"));
                return submit;
            }).collect(Collectors.toList());
//          发送短信到mq 等待策略模块进行处理

            pushSubmitToQueueService.sendSubmitToQueue(list);

            //不符合规则的手机号我们可以立刻返回
            return fail;
        }
//        1 缓存中没有查到  去查询数据库

//        直接仍异常
        throw new MybaseException(ResutlDataEnum.CLIENTIDERROR);//用户不存在

    }
}
